from PyQt4.QtCore import *
from PyQt4.QtGui import *
from core import cmds
from ui.graph import *

class RelationalGraphView(QGraphicsView):
    def __init__(self,parent=None):
        QGraphicsView.__init__(self, parent)
        self.setObjectName("Graph")
        self._scene = RelationalGraphScene(self)
        self.setScene(self._scene)
        self.centerOn(1000,1000)
        self.setInteractive(True)
        self.setDragMode(QGraphicsView.RubberBandDrag)
        self.setAcceptDrops(True)
        
        
    def dragEnterEvent(self, event):
        
        mimedata = event.mimeData()
        if not mimedata.hasFormat('text/plain'):
            event.ignore()
        
        if event.source() == self:
            event.setDropAction(QtCore.Qt.MoveAction)
            event.accept()
        else:
            event.acceptProposedAction()

    dragMoveEvent = dragEnterEvent
    
        
    def dropEvent(self, event):
        mimedata = event.mimeData()
        data = cmds.object_from_string(str(mimedata.text()))
        if data is None:
            return
        
        if cmds.is_type(data):
            data = data()
        
        self.scene().add_node(data)
        #self.scene().reset()
        return QGraphicsView.dropEvent(self, event)
        
    def keyReleaseEvent(self, event):
      if event.key() == 16777251:
        self.setDragMode(QGraphicsView.RubberBandDrag)

    def keyPressEvent(self, event):
        if event.key() == 16777251:
            self.setDragMode(QGraphicsView.ScrollHandDrag)
        if event.text() == '+':
            self.scale(1.1,1.1)
        if event.text() == '-':
            self.scale(0.9,0.9)

class RelationalGraphScene(QGraphicsScene):
    
    def __init__(self,parent=None):
        QGraphicsScene.__init__(self, parent)
        self.setObjectName("GraphScene")
        self._canvas_size = 2000
        self._node_widget = NodeWidget
        self._active_tool = None
        
        
    def delete_item(self):
        focus_item = self.focusItem()
        if focus_item is None: return
        
        if isinstance(focus_item, NodeProxyWidget):
            self.remove_node_item(focus_item)
            
        elif isinstance(focus_item, EdgeItem):
            self.remove_edge_item(focus_item)
    
        
    def itemHoverEnter(self, item):
        self.setFocusItem(item)
        if not self._active_tool is None and hasattr(self._active_tool, 'on_item_enter'):
            self._active_tool.on_item_enter(item)
            
    def itemHoverLeave(self, item):
        self.clearFocus()
        if not self._active_tool is None and hasattr(self._active_tool, 'on_item_leave'):
            self._active_tool.on_item_leave(item)
        
    def activate_tool(self, tool):
        if not isinstance(tool, Tool):
            return
        self._active_tool = tool
        
    def deactivate_tool(self):
        self._active_tool = None
    
    def mouseMoveEvent(self, event):
        if not self._active_tool is None and hasattr(self._active_tool, 'on_mouse_move'):
            self._active_tool.on_mouse_move(event)
        return QGraphicsScene.mouseMoveEvent(self, event)
    
    def mouseReleaseEvent(self, event):
        if not self._active_tool is None and hasattr(self._active_tool, 'on_mouse_release'):
            self._active_tool.on_mouse_release(event)
        return QGraphicsScene.mouseReleaseEvent(self, event)
        
    
    @apply
    def canvas_size():
        def set_canvas_size(self, size):
            self._canvas_size = size
            self._update_rect()
        def get_canvas_size(self): 
            return self._canvas_size    
        return property(get_canvas_size, set_canvas_size) 
    
    
    def current_component(self):
        sel_items = self.selectedItems()
        if len(sel_items) > 0:
            return sel_items[-1]._node
    
    def update_edge_positions(self):
        for edge in self.edge_items():
            edge.update_position()
            
    def edge_items(self):
        for item in self.items():
            if isinstance(item, EdgeItem):
                yield item
    
    def _update_rect(self):
        self.setSceneRect(-self.canvas_size,-self.canvas-size,
                          self.canvas_size*2,self.canvas_size*2)
  
    def item_from_node(self, node):
        for item in self.items():
            if not hasattr(item, '_node'): continue
            if item._node == node:
                return item
  
    def layout_nodes(self, layout_dict):
        for node, pos in layout_dict.iteritems():
            item = self.item_from_node(node)
            item.setPos(pos[0], pos[1])
     
    def add_edge(self, out_node, out_attr, in_node, in_attr):
        out_item = self.item_from_node(out_node)
        in_item = self.item_from_node(in_node)
        out_attr_item = out_item.attr_item(out_attr)
        in_attr_item = in_item.attr_item(in_attr)
        if in_attr_item is None or out_attr_item is None: return
        self.addItem(EdgeItem(out_attr_item, in_attr_item))
     
    def add_node(self, node):
        widget = NodeWidget()
        proxy = NodeProxyWidget(None, node, widget)
        self.addItem(proxy)
        return proxy


class RelationalGraph(ni.View):
    widget = RelationalGraphView
    
    def setup_widget(self, widget):
        QObject.connect(widget.scene(), SIGNAL("selectionChanged()"), 
                        lambda w=widget: self.graph_selection_changed(w))
    
    def graph_selection_changed(self, widget):
        comp = widget.scene().current_component()
        if comp is None: return
        cmds.select(comp)
        
    def current_changed(self, component):
        pass